home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The CICA Windows Explosion!
/
The CICA Windows Explosion! - Disc 2.iso
/
programr
/
dpmigcc5.zip
/
RSX
/
SOURCE
/
LOADER
/
LOADER.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-12-12
|
12KB
|
467 lines
/*****************************************************************************
* FILE: loader.c *
* *
* DESC: loader for 32bit RSX compiled with EMX/GCC *
* *
* Copyright (C) 1994 *
* Rainer Schnitker, Heeper Str. 283, 33607 Bielefeld *
* email: rainer@mathematik.uni-bielefeld.de *
* *
* See the files "README" and "COPYING" for further copyright and warranty *
* information. *
* *
*****************************************************************************/
#include <dos.h>
#include "LOADER.H"
struct info {
unsigned long membytes;
unsigned long memaddress;
unsigned long text_start;
unsigned long data_start;
unsigned long bss_start;
unsigned long stack_start;
unsigned long init_brk;
unsigned long entry;
unsigned short code16sel;
unsigned short data16sel;
} info;
extern unsigned _psp;
WORD code32sel; /* RSX CS selector */
WORD data32sel; /* RSX DS selector */
DWORD stackp32; /* RSX satck pointer */
static void far *extdata; /* DOS memory for RSX */
static unsigned segm; /* segment address */
static char far * env_str; /* env far pointer */
static char cline[260]; /* arguments */
static int n_strlen(char *str)
{
char *s;
for (s = str; *s; ++s);
return (s - str);
}
static int f_strlen(char far *str)
{
char far *s;
for (s = str; *s; ++s);
return ((int)(char near *)s - (int)(char near *)str);
}
static char *my_strcpy(char *string1, char *string2)
{
char *dst = string1;
while ((*dst = *string2) != 0)
++dst, ++string2;
return (string1);
}
static void error(char *s)
{
dos_puts("loader v1.0 : (c) Rainer Schnitker\n\r$");
dos_puts("rsx_32 loader error: $");
dos_puts(s);
}
static int skip_exe_hdr(int filehandle, DWORD * headoff)
{
struct exe_hdr exehdr;
exehdr.signatur = 0;
dos_read(filehandle, &exehdr, sizeof(WORD) * 3);
if (exehdr.signatur == 0x5a4d) { /* falls exe-kopf */
*headoff += (DWORD) exehdr.high * 512L;
if (exehdr.low)
*headoff += (DWORD) exehdr.low - 512L;
}
if (dos_lseek(filehandle, *headoff, SEEK_SET) != -1L)
return 0;
else {
*headoff = 0;
dos_lseek(filehandle, 0, SEEK_SET);
return -1;
}
}
static int argvenv(int argc, char **argv)
{
DWORD far * vectors; /* building argv, env */
WORD len; /* current len of string */
WORD stkp; /* current stack pos */
WORD count = 3; /* 0=argc 1=argv 2=env */
int i, envc = 0;
static char npx_str[] = "RSX_x87=?";
/* instead allocate memory, take some EMX space at DS:0x8000 */
vectors = (DWORD far *) (((DWORD)segm << 16) | 0x8000);
/* EMX program stack pointer */
/* stack grows down from DS:0xFFFC */
stkp = (WORD) stackp32;
FP_SEG(extdata) = segm;
FP_OFF(extdata) = stkp;
/* store env strings in user stack, built vectors */
for (; *env_str; ) {
len = f_strlen(env_str) + 1;
stkp -= len;
stkp &= ~3;
FP_OFF(extdata) = stkp;
far_memcpy(extdata, env_str, len);
vectors[count++] = (DWORD) stkp;
env_str += len;
envc ++;
}
/* put 387 status on env */
i = npx_installed();
npx_str[8] = (char) i + '0';
len = sizeof(npx_str) + 1;
stkp -= len;
stkp &= ~3;
FP_OFF(extdata) = stkp;
far_memcpy(extdata, (char far *)npx_str, len);
vectors[count++] = (DWORD) stkp;
env_str += len;
envc ++;
vectors[count++] = 0L; /* last is a NULL pointer */
/* store arg strings in user stack, built vectors */
for (i = 0; i < argc; i++) {
len = f_strlen(argv[i]) + 1;
stkp -= len;
stkp &= ~3;
FP_OFF(extdata) = stkp;
far_memcpy(extdata, (void far *) argv[i], len);
vectors[count] = (DWORD) stkp;
count++;
}
vectors[count++] = 0L; /* last is a NULL pointer */
len = count * sizeof(long);
stkp -= len;
vectors[0] = argc;
vectors[1] = stkp + (4 + envc) * sizeof(long); /* & vectors[3+nenvp+1] */
vectors[2] = stkp + 3 * sizeof(long); /* & vectors[3] */
FP_OFF(extdata) = stkp;
far_memcpy(extdata, vectors, len);
stackp32 = stkp; /* save current pos! (for entry) */
stackp32 += 3 * sizeof(long);
return 0;
}
static int read_in(int fhandle, DWORD address, long size)
{
#define READ_MAX 0xFF00
void far *dosmemp;
WORD word_size;
FP_OFF(dosmemp) = 0;
while (size != 0L) {
FP_SEG(dosmemp) = (WORD) (address >> 4);
word_size = (size >> 16) ? READ_MAX : (WORD) size;
dos_read_far(fhandle, dosmemp, word_size);
address += (DWORD) READ_MAX;
size -= (DWORD) word_size;
}
return 0;
}
static int load_protected_program(char *filename)
{
GNUOUT aout_hdr;
DWORD sizetext, sizedata, sizestack;
DWORD headoff;
int fhandle;
if ((fhandle = dos_open(filename, DO_RDONLY | DO_DENYWR)) == -1) {
error("open rsx32 error\r\n$");
return 1;
}
headoff = 0;
skip_exe_hdr(fhandle, &headoff);
/* read gnu aout header */
dos_read(fhandle, &aout_hdr, sizeof(aout_hdr));
/* test header */
if ((WORD) aout_hdr.a_info != 0x10b) {
error("illegal a.out header\r\n$");
dos_close(fhandle);
return 2;
}
sizetext = (aout_hdr.a_text + SEGMENT_SIZE - 1L) & ~(SEGMENT_SIZE - 1L);
sizedata = aout_hdr.a_data + ((aout_hdr.a_bss + 4095L) & ~4095L);
sizestack = 64 * 1024L;
info.text_start = N_TXTADDR(x);
info.data_start = info.text_start + sizetext;
info.bss_start = info.data_start + aout_hdr.a_data;
info.membytes = sizestack + sizetext + sizedata;
info.entry = aout_hdr.a_entry;
info.init_brk = info.data_start + sizedata;
stackp32 = info.text_start - 4L;
/* MEMORY per DOS besorgen */
if (!DosReallocParagraph(_psp, (WORD)(info.membytes>>4))) {
error("realloc memory error\r\n$");
return 3;
}
segm = _psp;
info.memaddress = (DWORD)segm << 4;
/* read in code */
dos_lseek(fhandle, headoff + N_TXTOFF(aout_hdr), SEEK_SET);
if (read_in(fhandle, info.memaddress + info.text_start, aout_hdr.a_text))
return 1;
/* read in data */
dos_lseek(fhandle, headoff + N_DATOFF(aout_hdr), SEEK_SET);
if (read_in(fhandle, info.memaddress + info.data_start, aout_hdr.a_data))
return 1;
dos_close(fhandle);
/* zero bss segment */
if (aout_hdr.a_bss) {
FP_SEG(extdata) = (WORD) ((info.memaddress + info.bss_start) >> 4);
FP_OFF(extdata) = (WORD) ((info.memaddress + info.bss_start) & 0xFL);
far_bzero(extdata, (WORD) aout_hdr.a_bss);
}
return 0;
}
static int real_to_protected(WORD mode)
{
static WORD DPMIdata_para_needed;
static WORD DPMIdata_segm_address;
WORD DPMIflags, DPMIversion;
BYTE processor;
DWORD PM_jump; /* switch to protmode jump */
if (GetDpmiEntryPoint(&PM_jump, &DPMIdata_para_needed,
&DPMIflags, &DPMIversion, &processor)) {
error("No DPMI-host found!\r\n$");
return -1;
}
if (mode == 1 && !(DPMIflags & 1)) {
error("32bit programs not supported by Host\r\n$");
return -1;
}
if (DPMIdata_para_needed) { /* get DPMI ring 0 stack */
DPMIdata_segm_address = GetDpmiHostParagraph(DPMIdata_para_needed);
if (!DPMIdata_segm_address) {
error("Can't alloc memory for the DPMI-host-stack\r\n$");
return -1;
}
}
if (DpmiEnterProtectedMode(PM_jump, mode, DPMIdata_segm_address)) {
error("can't switch to Protected Mode\r\n$");
return -1;
}
if (DPMIdata_para_needed)
LockLinRegion((DWORD) DPMIdata_segm_address << 4,
(DWORD) DPMIdata_para_needed << 4);
/* Now we are in Protected Mode */
info.code16sel = GetCS();
info.data16sel = GetDS();
return 0;
}
static void init_descriptors()
{
AllocLDT(2, &(code32sel));
data32sel = code32sel + SelInc();
SetBaseAddress(code32sel, info.memaddress);
SetBaseAddress(data32sel, info.memaddress);
SetAccess(code32sel, APP_CODE_SEL, DEFAULT_BIT | GRANULAR_BIT);
SetAccess(data32sel, APP_DATA_SEL, DEFAULT_BIT | GRANULAR_BIT);
SetLimit(code32sel, info.membytes - 1);
SetLimit(data32sel, info.membytes - 1);
}
static void get_cmdline_from_psp(unsigned psp_segm)
{
int z, env_seg;
char far *cmdl;
/* get envoronment segment from PSP */
env_seg = *(int far *) (((DWORD) psp_segm << 16) | 0x2c);
/* build far pointer to environment */
cmdl = (char far *) ((DWORD) env_seg << 16);
/* save environment pointer */
env_str = (char far *) ((DWORD) env_seg << 16);
/* skip env-strings ; last has two 0-bytes */
for (;;) {
if (*cmdl == '\0' && *(cmdl+1) == '\0')
break;
cmdl++;
}
cmdl += 4;
/* copy arg0 */
for (z = 0; z < sizeof(cline); z++) {
cline[z] = *cmdl;
if (cline[z] == '\0')
break;
cmdl++;
}
cline[z++] = ' ';
/* build cmdline far pointer from PSP */
cmdl = (char far *) ((DWORD) psp_segm << 16 | 0x81);
/* copy arg1,arg2,... */
for ( ; z < sizeof(cline) ; z++) {
cline[z] = *cmdl;
if (cline[z] == 13)
break;
cmdl++;
}
cline[z] = '\0';
}
static void build_args(int *argn, char ***argvp, int stub_opt)
{
static char extra[] = "!RSX";
static char *argvec[20];
int argc, src, dst, bs, quote;
char *q;
argc = 0;
dst = src = 0;
if (stub_opt)
argvec[argc++] = extra;
while (cline[src] == ' ' || cline[src] == '\t' || cline[src] == '\n')
++src;
do {
if (cline[src] == 0)
q = NULL;
else {
q = cline + dst;
bs = 0;
quote = 0;
for (;;) {
if (cline[src] == '"') {
while (bs >= 2) {
cline[dst++] = '\\';
bs -= 2;
}
if (bs & 1)
cline[dst++] = '"';
else
quote = !quote;
bs = 0;
} else if (cline[src] == '\\')
++bs;
else {
while (bs != 0) {
cline[dst++] = '\\';
--bs;
}
if (cline[src] == 0 ||
((cline[src] == ' ' || cline[src] == '\t') && !quote))
break;
cline[dst++] = cline[src];
}
++src;
}
while (cline[src] == ' ' || cline[src] == '\t'
|| cline[src] == '\n')
++src;
cline[dst++] = 0;
}
argvec[argc++] = q;
} while (q != NULL);
*argn = argc - 1;
*argvp = (char **) &(argvec[0]);
}
int main(void)
{
int argc;
char **argv;
char exe_name[130];
get_cmdline_from_psp(_psp);
build_args(&argc, &argv, 0);
my_strcpy(exe_name, argv[0]);
if (argc == 2 && argv[1][0]=='-' && argv[1][1] == '/' && argv[1][6] == '/') {
unsigned newpsp;
int i;
char s;
newpsp = 0;
for ( i=2 ; i<=5 ; i++) {
s = argv[1][i];
if (s >= 'A')
s -= ('A' - 10);
else
s -= '0';
newpsp <<= 4;
newpsp |= s;
}
get_cmdline_from_psp(newpsp);
build_args(&argc, &argv, 1);
}
if (argc > 7 && argv[1][0]=='!' && argv[1][1] == 'p' && argv[1][5] == 'y') {
unsigned newpsp;
int i;
char s;
newpsp = 0;
for ( i=0 ; i<=3 ; i++) {
s = argv[7][i];
if (s >= 'a')
s -= ('a' - 10);
else if (s >= 'A')
s -= ('A' - 10);
else
s -= '0';
newpsp <<= 4;
newpsp |= s;
}
get_cmdline_from_psp(newpsp);
build_args(&argc, &argv, 1);
}
if (load_protected_program(exe_name))
return(1);
if (argvenv(argc, argv))
return (1);
if (real_to_protected(1))
return (1);
init_descriptors();
jmp_to_user();
return 0;
}